package models

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
	"sync"
	"sync/atomic"
	"time"

	"go-gateworker/internal/circuitbreaker"
	"go-gateworker/internal/config"
)

// ServerStatus 服务器状态
type ServerStatus int

const (
	StatusHealthy     ServerStatus = iota // 健康状态
	StatusOverloaded                      // 过载状态
	StatusUnhealthy                       // 不健康状态
	StatusBlacklisted                     // 黑名单状态
	StatusRetrying                        // 重试状态
)

// Server 表示一个后端服务器
type Server struct {
	URL            *url.URL
	status         ServerStatus
	failCount      int64     // 连续失败次数
	lastFailTime   time.Time // 最后一次失败时间
	ReverseProxy   *httputil.ReverseProxy
	LoadMetric     int64 // 使用 atomic 操作
	Transport      *http.Transport
	mu             sync.RWMutex // 保护状态相关字段
	Config         config.ServerConfig
	CircuitBreaker *circuitbreaker.CircuitBreaker // 熔断器
}

// NewServer 创建一个新的服务器实例
func NewServer(cfg config.ServerConfig) (*Server, error) {
	u, err := url.Parse(cfg.URL)
	if err != nil {
		return nil, err
	}

	transport := &http.Transport{
		MaxIdleConns:        cfg.MaxIdleConns,
		MaxIdleConnsPerHost: cfg.MaxIdleConnsPerHost,
		MaxConnsPerHost:     cfg.MaxConnsPerHost,
	}

	server := &Server{
		URL:       u,
		status:    StatusHealthy,
		Transport: transport,
		Config:    cfg,
	}

	// 初始化熔断器
	if cfg.CircuitBreaker != nil {
		server.CircuitBreaker = circuitbreaker.New(*cfg.CircuitBreaker)
		log.Printf("[INFO] 为服务器 %s 创建熔断器, 错误阈值: %.1f%%, 最小请求数: %d",
			u.String(), cfg.CircuitBreaker.ErrorThreshold, cfg.CircuitBreaker.MinimumRequests)
	}

	server.ReverseProxy = &httputil.ReverseProxy{
		Transport: transport,
		Director: func(req *http.Request) {
			// 只设置目标主机，不动 path
			req.URL.Scheme = server.URL.Scheme
			req.URL.Host = server.URL.Host
			req.Host = server.URL.Host
			// 不要有任何 path 拼接或赋值
		},
		ModifyResponse: func(resp *http.Response) error {
			log.Printf("收到后端响应: %d %s -> %s", resp.StatusCode, resp.Request.URL.Path, server.URL.String())
			return nil
		},
		ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
			// 获取请求ID用于日志关联
			requestID := r.Header.Get("X-Request-ID")
			if requestID == "" {
				requestID = "unknown"
			}

			// 记录详细的错误信息
			log.Printf("[ERROR] [%s] 代理错误: %v, 目标服务器: %s, 路径: %s",
				requestID, err, server.URL.String(), r.URL.Path)

			// 标记服务失败
			server.MarkFailure()

			// 如果有熔断器，更新熔断器状态
			if server.CircuitBreaker != nil {
				server.CircuitBreaker.AfterRequest(false)

				// 获取熔断器状态
				cbStats := server.CircuitBreaker.GetStats()
				log.Printf("[INFO] [%s] 熔断器状态: %s, 错误率: %.2f%%, 总请求: %d",
					requestID, cbStats["state"], cbStats["error_rate"], cbStats["total_requests"])
			}

			// 设置适当的HTTP状态码
			statusCode := http.StatusServiceUnavailable
			w.Header().Set("Content-Type", "application/json")
			w.Header().Set("Retry-After", "30")
			w.WriteHeader(statusCode)

			// 返回结构化错误信息
			errMsg := fmt.Sprintf(`{"error":"Service Unavailable","message":"请求处理失败","request_id":"%s"}`, requestID)
			w.Write([]byte(errMsg))
		},
	}

	return server, nil
}

// GetLoad 获取服务器当前负载
func (s *Server) GetLoad() int64 {
	return atomic.LoadInt64(&s.LoadMetric)
}

// IncrementLoad 增加服务器负载
func (s *Server) IncrementLoad() bool {
	current := atomic.LoadInt64(&s.LoadMetric)
	if current >= s.Config.LoadThreshold {
		return false
	}
	atomic.AddInt64(&s.LoadMetric, 1)
	return true
}

// DecrementLoad 减少服务器负载
func (s *Server) DecrementLoad() {
	atomic.AddInt64(&s.LoadMetric, -1)
}

// MarkFailure 标记服务器失败
func (s *Server) MarkFailure() {
	s.mu.Lock()
	defer s.mu.Unlock()

	atomic.AddInt64(&s.failCount, 1)
	s.lastFailTime = time.Now()

	// 如果连续失败次数超过阈值，标记为不健康
	if atomic.LoadInt64(&s.failCount) >= s.Config.MaxFailCount {
		if s.status == StatusHealthy {
			s.status = StatusUnhealthy
			log.Printf("Server %s marked as unhealthy due to consecutive failures", s.URL)
		} else if s.status == StatusUnhealthy {
			s.status = StatusBlacklisted
			log.Printf("Server %s added to blacklist", s.URL)
		}
	}
}

// MarkSuccess 标记服务器成功
func (s *Server) MarkSuccess() {
	s.mu.Lock()
	defer s.mu.Unlock()

	if s.status != StatusHealthy {
		s.status = StatusHealthy
		atomic.StoreInt64(&s.failCount, 0)
		log.Printf("Server %s recovered and marked as healthy", s.URL)
	}
}

// IsAvailable 检查服务器是否可用
func (s *Server) IsAvailable() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.status == StatusHealthy || s.status == StatusOverloaded
}

// GetStatus 获取服务器状态
func (s *Server) GetStatus() ServerStatus {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.status
}

// IsRetrying 检查是否正在重试
func (s *Server) IsRetrying() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.status == StatusRetrying
}

// IsHealthy 检查是否健康
func (s *Server) IsHealthy() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.status == StatusHealthy
}

// StartRetry 开始重试
func (s *Server) StartRetry() {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.status != StatusRetrying {
		s.status = StatusRetrying
		log.Printf("Server %s entering retry state", s.URL)
	}
}

// LastFailTime 获取最后失败时间
func (s *Server) LastFailTime() time.Time {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.lastFailTime
}

// ResetStatus 重置服务器状态
func (s *Server) ResetStatus() {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.status = StatusHealthy
	atomic.StoreInt64(&s.failCount, 0)
	log.Printf("Server %s status reset to healthy", s.URL)
}
